use axum_ifnk_common::prelude::LoggingConfig;
use color_eyre::eyre::{Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    pub server: ServerConfig,
    pub logging: LoggingConfig,
    pub paths: PathsConfig,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
    pub host: String,
    pub port: u16,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PathsConfig {
    pub data_root: String,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            server: ServerConfig::default(),
            logging: LoggingConfig::default(),
            paths: PathsConfig::default(),
        }
    }
}

impl Default for ServerConfig {
    fn default() -> Self {
        Self {
            host: "127.0.0.1".to_string(),
            port: 3000,
        }
    }
}

impl Default for PathsConfig {
    fn default() -> Self {
        let default_path = Path::new(env!("CARGO_MANIFEST_DIR"))
            .join("..")
            .join("voice-proj-new")
            .join("voice-api")
            .join("bin")
            .join("Debug")
            .join("net8.0");

        Self {
            data_root: default_path.to_string_lossy().to_string(),
        }
    }
}

impl Config {
    /// 验证配置的有效性
    pub fn validate(&self) -> Result<()> {
        let mut errors = Vec::new();

        // 验证服务器端口范围
        if self.server.port == 0 {
            errors.push("服务器端口不能为 0".to_string());
        }

        // 验证主机地址格式
        if self.server.host.is_empty() {
            errors.push("服务器主机地址不能为空".to_string());
        }

        // 验证日志级别
        let valid_levels = ["trace", "debug", "info", "warn", "error"];
        if !valid_levels.contains(&self.logging.level.as_str()) {
            errors.push(format!(
                "无效的日志级别 '{}', 有效值: {}",
                self.logging.level,
                valid_levels.join(", ")
            ));
        }

        // 验证日志格式
        let valid_formats = ["pretty", "json", "compact"];
        if !valid_formats.contains(&self.logging.format.as_str()) {
            errors.push(format!(
                "无效的日志格式 '{}', 有效值: {}",
                self.logging.format,
                valid_formats.join(", ")
            ));
        }

        // 验证日志轮转策略
        let valid_rotations = ["daily", "hourly", "never"];
        if !valid_rotations.contains(&self.logging.file_rotation.as_str()) {
            errors.push(format!(
                "无效的日志轮转策略 '{}', 有效值: {}",
                self.logging.file_rotation,
                valid_rotations.join(", ")
            ));
        }

        // 验证 data_root 路径存在性（关键改进）
        let data_path = Path::new(&self.paths.data_root);
        if !data_path.exists() {
            errors.push(format!(
                "配置的 data_root 路径不存在: '{}'
  提示: 请在 config.toml 中配置正确的数据根目录，或创建该目录",
                self.paths.data_root
            ));
        }

        // 一次性返回所有错误，提供完整的问题清单
        if !errors.is_empty() {
            return Err(color_eyre::eyre::eyre!(
                "配置验证失败，发现 {} 个问题:\n{}",
                errors.len(),
                errors
                    .iter()
                    .enumerate()
                    .map(|(i, e)| format!("  {}. {}", i + 1, e))
                    .collect::<Vec<_>>()
                    .join("\n")
            ));
        }

        Ok(())
    }
}

/// 从配置文件加载配置
pub fn load_config() -> Result<Config> {
    const CONFIG_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/config.toml");
    let config_path = Path::new(CONFIG_PATH);

    // 检查配置文件是否存在
    if !config_path.exists() {
        tracing::warn!("配置文件 {} 不存在，使用默认配置", config_path.display());
        let config = Config::default();
        config.validate()?;
        return Ok(config);
    }

    // 读取配置文件
    let config_content = fs::read_to_string(config_path)
        .context("读取配置文件失败")?;

    // 解析 TOML，使用 context 提供提示
    let config: Config = toml::from_str(&config_content)
        .context("解析 TOML 配置文件失败")?;

    // 验证配置
    config.validate()?;

    tracing::info!("成功加载配置文件: {}", config_path.display());
    Ok(config)
}
